<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Programming in Lua : 25.3</title>
<link rel="stylesheet" type="text/css" href="pil.css">
</head>
<body>
<p class="warning">
<A HREF="contents.html"><IMG TITLE="Programming in Lua (first edition)" SRC="capa.jpg" ALT="" ALIGN="left"></A>This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.<BR>The third edition targets Lua 5.2 and is available at <A HREF="http://www.amazon.com/exec/obidos/ASIN/859037985X/theprogrammil3-20">Amazon</A> and other bookstores.<BR>By buying the book, you also help to <A HREF="../donations.html">support the Lua project</A>.
</p>
<table width="100%" class="nav">
<tr>
<td width="10%" align="left"><a href="25.2.html"><img border="0" src="left.png" alt="Previous"></a></td>
<td width="80%" align="center"><a href="contents.html"><font face="Helvetica,Arial,sanserif">
<font color="gray">Programming in </font><font color="blue"> Lua</font>
</font></a></td>
<td width="10%" align="right"><a href="26.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
<tr>
<td width="10%" align="left"></td>
<td width="80%" align="center"><a href="contents.html#P4">Part IV. The C API</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="contents.html#25">Chapter 25. Extending your Application</a></td>
<td width="10%" align="right"></td></tr>
</table>
<hr/>
<p><h2>25.3 &ndash; A Generic Call Function</h2>

<p>As a more advanced example,
we will build a wrapper for calling Lua functions,
using the <code>vararg</code> facility in C.
Our wrapper function (let us call it <code>call_va</code>) receives the
name of the function to be called,
a string describing the types of the arguments and results,
then the list of arguments, and finally a list of pointers to
variables to store the results;
it handles all the details of the API.
With this function, we could write our previous example
simply as
<pre>
    call_va("f", "dd>d", x, y, &amp;z);
</pre>
where the string <code>"dd>d"</code> means
"two arguments of type double, one result of type double".
This descriptor can use the letters `<code>d</code>&acute; for double,
`<code>i</code>&acute; for integer, and `<code>s</code>&acute; for strings;
a `<code>></code>&acute; separates arguments from the results.
If the function has no results, the `<code>></code>&acute; is optional.
<pre>
    #include &lt;stdarg.h>
    
    void call_va (const char *func, const char *sig, ...) {
      va_list vl;
      int narg, nres;  /* number of arguments and results */
    
      va_start(vl, sig);
      lua_getglobal(L, func);  /* get function */
    
      /* push arguments */
      narg = 0;
      while (*sig) {  /* push arguments */
        switch (*sig++) {
    
          case 'd':  /* double argument */
            lua_pushnumber(L, va_arg(vl, double));
            break;
    
          case 'i':  /* int argument */
            lua_pushnumber(L, va_arg(vl, int));
            break;
    
          case 's':  /* string argument */
            lua_pushstring(L, va_arg(vl, char *));
            break;
    
          case '>':
            goto endwhile;
    
          default:
            error(L, "invalid option (%c)", *(sig - 1));
        }
        narg++;
        luaL_checkstack(L, 1, "too many arguments");
      } endwhile:
    
      /* do the call */
      nres = strlen(sig);  /* number of expected results */
      if (lua_pcall(L, narg, nres, 0) != 0)  /* do the call */
        error(L, "error running function `%s': %s",
                 func, lua_tostring(L, -1));
    
      /* retrieve results */
      nres = -nres;  /* stack index of first result */
      while (*sig) {  /* get results */
        switch (*sig++) {
    
          case 'd':  /* double result */
            if (!lua_isnumber(L, nres))
              error(L, "wrong result type");
            *va_arg(vl, double *) = lua_tonumber(L, nres);
            break;
    
          case 'i':  /* int result */
            if (!lua_isnumber(L, nres))
              error(L, "wrong result type");
            *va_arg(vl, int *) = (int)lua_tonumber(L, nres);
            break;
    
          case 's':  /* string result */
            if (!lua_isstring(L, nres))
              error(L, "wrong result type");
            *va_arg(vl, const char **) = lua_tostring(L, nres);
            break;
    
          default:
            error(L, "invalid option (%c)", *(sig - 1));
        }
        nres++;
      }
      va_end(vl);
    }
</pre>
Despite its generality,
this function follows the same steps of our previous example:
It pushes the function, pushes the arguments,
does the call, and gets the results.
Most of its code is straightforward,
but there are some subtleties.
First, it does not need to check whether <code>func</code> is a function;
<code>lua_pcall</code> will trigger any occasional error.
Second, because it pushes an arbitrary number of arguments,
it must check the stack space.
Third, because the function may return strings,
<code>call_va</code> cannot pop the results from the stack.
It is up to the caller to pop them,
after it finishes using occasional string results
(or after copying them to other buffers).

<p>
<hr/>
<table width="100%" class="nav">
<tr valign="top">
<td width="90%" align="left">
<small>
  Copyright &copy; 2003&ndash;2004 Roberto Ierusalimschy.  All rights reserved.
</small>
</td>
<td width="10%" align="right"><a href="26.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
</table>


</body></html>

